package component;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import tools.FileUtil;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

public class WebDriverFactory extends AbstractFactoryBean<WebDriver> {
    @Override
    public Class<?> getObjectType() {
        return WebDriver.class;
    }

    boolean useChrome = true;

    public WebDriverFactory() {
    }

    public WebDriverFactory(boolean useChrome) {
        this.useChrome = useChrome;
    }

    @Override
    protected WebDriver createInstance() throws Exception {
        if (useChrome){
            return createChromeInstance();
        }else {
            return createFirefoxInstance();
        }
    }

    private WebDriver createChromeInstance(){
        ChromeOptions options = new ChromeOptions();
//        File compileTargetDom = new File(this.getClass().getResource("/").getPath());
//        File tempPath = new File(compileTargetDom.getParentFile().getParentFile(),"temp");
//        File tempPath = FileUtil.getProjectResource("temp");
//        System.out.println("tempPath = " + tempPath);
//        options.addArguments("--user-data-dir="+tempPath.getAbsolutePath());
        File downloadPath = FileUtil.getProjectResource("download");
        Map<String,Object> prefs = new HashMap<>();
        prefs.put("profile.default_content_settings.popups",0);
        prefs.put("download.default_directory",downloadPath.getAbsolutePath());

        options.setExperimentalOption("prefs",prefs);

        return CloseableChromeDriver.getInstance(options);
    }

    private WebDriver createFirefoxInstance(){
        FirefoxProfile profile = new FirefoxProfile();
        profile.setPreference("browser.download.folderList", 2);
        profile.setPreference("browser.download.manager.showWhenStarting", false);
        File downloadPath = FileUtil.getProjectResource("download");
        profile.setPreference("browser.download.dir", downloadPath.getAbsolutePath()); // 设置下载文件夹的路径

        FirefoxOptions options = new FirefoxOptions();
        options.setProfile(profile);
        options.setBinary("C:\\Program Files\\Mozilla Firefox\\firefox.exe");

        // 设置Firefox驱动程序的路径
//        System.setProperty("webdriver.gecko.driver", "/path/to/geckodriver");

        return CloseableFirefoxDriver.getInstance(options);
    }

    static class CloseableChromeDriver extends ChromeDriver {
        WeakReference<Thread> shutdownHookReference;
        static WeakReference<CloseableChromeDriver> instance;

        protected CloseableChromeDriver(ChromeOptions options) {
            super(options);
            Thread thread = new Thread("ChromeDriverDestory"){
                @Override
                public void run() {
                    CloseableChromeDriver.this.quit();
                }
            };
            instance = new WeakReference<>(this);
            shutdownHookReference = new WeakReference<>(thread);
            Runtime.getRuntime().addShutdownHook(thread);
        }

        public static CloseableChromeDriver getInstance(ChromeOptions options) {
            if (instance!=null && instance.get()!=null){
                return instance.get();
            }
            return new CloseableChromeDriver(options);
        }
    }

    static class CloseableFirefoxDriver extends FirefoxDriver {
        WeakReference<Thread> shutdownHookReference;
        static WeakReference<CloseableFirefoxDriver> instance;

        protected CloseableFirefoxDriver(FirefoxOptions options) {
            super(options);
            Thread thread = new Thread("FirefoxDriverDestory"){
                @Override
                public void run() {
                    CloseableFirefoxDriver.this.quit();
                }
            };
            instance = new WeakReference<>(this);
            shutdownHookReference = new WeakReference<>(thread);
            Runtime.getRuntime().addShutdownHook(thread);
        }

        public static CloseableFirefoxDriver getInstance(FirefoxOptions options) {
            if (instance!=null && instance.get()!=null){
                return instance.get();
            }
            return new CloseableFirefoxDriver(options);
        }
    }
}
